/*
	jGrouse framework
	Copyright 2007 by Denis Riabtchik 
	All rights reserved.
	
	Licensed under modified BSD license. See license.txt for details
*/

/**
	@module jgrouse.util.TaskManager
	@requires jgrouse.util.PropertyChangeSupport
*/
jgrouse.module(
{
	name : 'jgrouse.util.TaskManager', 
	requires : ['jgrouse.util.PropertyChangeSupport'],
	imports : ['jgrouse.util.PropertyChangeSupport', 'jgrouse.util.PropertyChangeEvent'],
	body : function(embed)
	{
		eval(embed);
		
		var timer = null;
		var queue = [];
		
		function asyncRunner()
		{
			var tmp = queue;
			queue = [];
			timer = null;
			for (var i = 0; i < tmp.length; i++)
			{
				tmp[i]();
			}
		}
		
		/**
			Utility for asynchrous execution of functions and property change notifications.
			Applications can register listeners for global property changes into that object
			@struct jgrouse.util.TaskManager
			@implements jgrouse.util.PropertyChangeSupport 
		*/		
		jgrouse.util.TaskManager = 
		{
			_pcs : null,
			
			/**
				Schedule function for asynchronous execution
				@function post
				@param {function()} func - function to be executed asynchronously
			*/
			post : function(func)
			{
				queue.push(func);
				if (!timer)
				{
					timer = window.setTimeout(asyncRunner, 10);
				}
			},
			
			/**
				Schedule asynchronous notification about property change
				@function postPropertyChange
				@param {string} propertyName - name of property that is being changed
				@param {object} newValue - new value of property 
				@param {object} oldValue - old value of property
				@param {object} sender - sender of the event, optional
			*/
			postPropertyChange : function(propertyName, newValue, oldValue, sender)
			{
				var athis = this;
				this.post(function()
				{
					athis._pcs.firePropertyChange(propertyName, newValue, oldValue, sender);	
				})
			},
			
			onPropertyChanged : function(e)
			{
				this.handlePropertyChangeEvent(e);
			}
		}
		
		jgrouse.util.TaskManager._pcs = new PropertyChangeSupport(jgrouse.util.TaskManager),
		
		jgrouse.delegate(jgrouse.util.TaskManager, '_pcs', PropertyChangeSupport.prototype);
		
		/**
			Base class for event pollers
			@class jgrouse.util.EventPoller
			@extends jgrouse.BaseObject
		*/
		jgrouse.define('jgrouse.util.EventPoller', 'jgrouse.BaseObject', function(embed)
		{
			eval(embed);
			
			return {
				/**
					@constructor initialize
					@param {int} timeout - poll frequency (in ms). Default is 500ms
				*/
				initialize : function(timeout)
				{
					_sup(this, arguments);
					this._pcs = new PropertyChangeSupport(this);
					this._subscribersCount = 0;
					this._timer = null;
					this._poller = jgrouse.bind(this, this.poll);
					this._timeout = timeout? timeout : 500;
				},
				
				_checkSubscribers : function()
				{
					if (this._subscribersCount && !this._timer)
					{
						this._timer = window.setInterval(this._poller, this._timeout);
					}
					if (!this._subscribersCount && this._timer)
					{
						window.clearInterval(this._timer);
						this._timer = null;
					}
				},
				
				/**
					Method that polls certain parameters and sends notifications whenever they are changed
					@function poll
				*/
				poll : function()
				{
					jgrouse.notImplemented(RTTI + '.poll');
				},
				
				/**
					Add listener
					@function addListener
					@param propertyNameOrListener
					@param listener
				*/
				addListener : function(propertyNameOrListener, listener)
				{
					this._pcs.addListener.apply(this._pcs, arguments);
					this._subscribersCount++;
					this._checkSubscribers();
					jgrouse.log.info('added subscriber, ' + this._subscribersCount);
				},
				
				/**
					Remove listener
					@function removeListener
					@param propertyNameOrListener
					@param listener
				*/
				removeListener : function(propertyNameOrListener, listener)
				{
					this._pcs.removeListener.apply(this._pcs, arguments);
					this._subscribersCount--;
					this._checkSubscribers();
					jgrouse.log.info('removed subscriber, ' + this._subscribersCount);
				}
			}
		});
		
	}
	
});
